<?php
function substr_utf8($str, $length, $start = 0, $suffix = '...')
{
    if (empty( $str ))
    {
        return $str;
    }
    
    $suffix_len = strlen( $suffix );
    if ($length <= $suffix_len)
    {
        $suffix = '';
        $suffix_len = 0;
    }
    
    if (function_exists( 'mb_strlen' ) && function_exists( 'mb_substr' ))
    {
        if (mb_strlen( $str, 'UTF-8' ) > $start + $length)
        {
            return mb_substr( $str, $start, $length - $suffix_len, 'UTF-8' ) . $suffix;
        }
        elseif ($start > 0)
        {
            return mb_substr( $str, $start, $length, 'UTF-8' );
        }
        else
        {
            return $str;
        }
    }
    
    // c:第几个字符；bi：开始字节；si，ei：结束字节
    $i = $c = $bi = $si = $ei = 0;
    $len = strlen( $str );
    while ( $i < $len )
    {
        $ord = ord( $str{$i} );
        // 通过分析utf8编码规则，发现一个正常字符的utf8编码可以分为两种情况：
        // 1.一个字节就是字符（ASII码）
        // 2.一个大于192的字节后面跟1~5个[128-192)的“填充”字节表示一个字符
        // 所以可以计算不在[128-192)范围内的字节数作为实际的字符数，
        // 通过记录实际字符在字节中的位置，调用字节截断来实现字符串截断。
        if ($ord < 128 || $ord >= 192)
        {
            if ($c == $start)
            {
                $bi = $i;
            }
            elseif ($c == $start + $length - $suffix_len)
            {
                $si = $i;
            }
            if ($c == $start + $length)
            {
                $ei = $i;
                break;
            }
            $c ++;
        }
        $i ++;
    }
    if ($ei == 0)
    {
        $ei = $len;
    }
    if ($ei < $len)
    {
        return substr( $str, $bi, $si - $bi ) . $suffix;
    }
    else
    {
        return substr( $str, $bi, $ei - $bi );
    }
}
function up_path($filename, $key = 'img', $default = 'images/default.png')
{
    if (empty( $filename ))
    {
        return $default;
    }
    return up_base( $key ) . $filename;
}
function thumb_path($filename, $w = 100, $h = 100, $q = 80, $m = 0, $default = 'images/default.png')
{
    if (empty( $filename ))
    {
        return $default;
    }
    $filename = preg_replace_callback( '/\.(jpg|png|gif)$/i', function ($matches) use($w, $h, $q, $m)
    {
        return '_' . radix( bin2hex( "T{$matches[1]}W{$w}H{$h}Q{$q}M{$m}" ), 62, 16 ) . '.jpg';
    }, $filename );
    return up_base( 'thumb' ) . $filename;
}
function up_base($key = 'img')
{
    $result = base_url() . 'public/';
    $CI = & get_instance();
    if (! empty( $CI->upload_folder[$key] ))
    {
        $result .= $CI->upload_folder[$key];
    }
    return $result;
}

/**
 * 十进制数转换成其它进制
 * 可以转换成2-62任何进制
 *
 * @param integer $num
 * @param integer $to
 * @param string $dict 输出字符串的字典
 * @return string
 */
function dec_to($num, $to = 62, $dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    if ($to == 10 || $to > 62 || $to < 2) {
        return $num;
    }
    $ret = '';
    do {
        $ret = $dict[bcmod($num, $to)] . $ret;
        $num = bcdiv($num, $to);
    } while ($num > 0);
    return $ret;
}
/**
 * 其它进制数转换成十进制数
 * 适用2-62的任何进制
 *
 * @param string $num
 * @param integer $from
 * @param string $dict //输入字符串的字典
 * @return number
 */
function dec_from($num, $from = 62, $dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    if ($from == 10 || $from > 62 || $from < 2) {
        return $num;
    }
    $num = strval($num);
    $len = strlen($num);
    $dec = 0;
    for($i = 0; $i < $len; $i++) {
        $pos = strpos($dict, $num[$i]);
        if ($pos === false || $pos >= $from) {
            continue; // 如果出现非法字符，会忽略掉。比如16进制中出现w、x、y、z等
        }
        $dec = bcadd(bcmul(bcpow($from, $len - $i - 1), $pos), $dec);
    }
    return $dec;
}
/**
 * 数字的任意进制转换
 *
 * @param integer|string $number
 * @param integer $to 目标进制数
 * @param integer $from 源进制数
 * @return string
 */
function radix($number, $to = 62, $from = 10, $to_dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', $from_dict = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
    // 先转换成10进制
    $number = dec_from($number, $from, $from_dict);
    // 再转换成目标进制
    $number = dec_to($number, $to, $to_dict);
    return $number;
}
/**
 * unicode编码转字符串
 * 
 * @param string $str            
 */
function unicode_escape($str)
{
    return preg_replace_callback( '/\\\u([0-9a-f]{4})/i', function ($match)
    {
        return mb_convert_encoding( pack( 'H*', $match[1] ), 'UTF-8', 'UCS-2BE' );
    }, $str );
}